﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Go.Model;
using tpGo;
using System.Net.Sockets;
using System.Net;
using System.Collections;
using System.IO;

namespace tpGo
{
    public partial class Form1 : Form
    {
        private const String JUGADORHUMANO = "Humano";
        private const String JUGADORCOMPUTADORA = "Computadora";
        private const String JUGADORREMOTO = "Remoto";
        private const String TABLERO9x9 = "9x9";
        private const String TABLERO19x19 = "19x19";
        Socket socketServer;
        Socket socketCliente;
        private static int PORT = 8222;
        private static String IP = "192.168.1.10";
        Go.Tools.Color colorJugadorRemoto;
        private static int TAMANIOTRANSFERENCIA = 50;
        private static String TABLERO = "boardsize";
        private static String COLORNEGRO = "Black";
        private static String COLORBLANCO = "White";
        
        public Form1()
        {
            InitializeComponent();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            Bitmap backgroundImage = new Bitmap(ImageConstants.DIRECTORY+ "go1.jpg");
            e.Graphics.DrawImage(backgroundImage, this.ClientRectangle,
                new Rectangle(0, 0, backgroundImage.Width, backgroundImage.Height),
                GraphicsUnit.Pixel);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            cargarTipoJugadorBlanca();
            cargarTipoJugadorNegra();
            cargarComboTablero();
            cargarComboBox1();
        }
        private void cargarComboBox1()
        {
            comboBox1.Items.Add(JUGADORHUMANO);
            comboBox1.Items.Add(JUGADORCOMPUTADORA);
        }

        private void cargarTipoJugadorBlanca() {
            tipoJugadorBlanca.Items.Add(JUGADORHUMANO);
            tipoJugadorBlanca.Items.Add(JUGADORCOMPUTADORA);
            tipoJugadorBlanca.Items.Add(JUGADORREMOTO);
            tipoJugadorBlanca.SelectedIndex = 0;
        }

        private void cargarTipoJugadorNegra()
        {
            tipoJugadorNegra.Items.Add(JUGADORHUMANO);
            tipoJugadorNegra.Items.Add(JUGADORCOMPUTADORA);
            tipoJugadorNegra.Items.Add(JUGADORREMOTO);
            tipoJugadorNegra.SelectedIndex = 0;
        }

        private void cargarComboTablero()
        {
            tamanoTablero.Items.Add(TABLERO9x9);
            tamanoTablero.Items.Add(TABLERO19x19);
            tamanoTablero.SelectedIndex = 0;
        }


        private String llenarBolaNegra()
        {
            String bolaNegra = "";
            switch (tipoJugadorNegra.SelectedIndex)
            {
                case 0:
                    bolaNegra = JUGADORHUMANO;
                    break;
                case 1:
                    bolaNegra = JUGADORCOMPUTADORA;
                    break;
                case 2:
                    bolaNegra = JUGADORREMOTO;
                    break;
                default:
                    bolaNegra = JUGADORHUMANO;
                    break;
            }
            return bolaNegra;
        }

        private String llenarBolaBlanca()
        {
            String bolaBlanca = "";

            switch (tipoJugadorBlanca.SelectedIndex)
            {
                case 0:
                    bolaBlanca = JUGADORHUMANO;
                    break;
                case 1:
                    bolaBlanca = JUGADORCOMPUTADORA;
                    break;
                case 2:
                    bolaBlanca = JUGADORREMOTO;
                    break;
                default:
                    bolaBlanca = JUGADORCOMPUTADORA;
                    break;
            }
            return bolaBlanca;
        }

        private int llenarTablero()
        {
            int dimsension = 0;
            switch (tamanoTablero.SelectedIndex)
            {
                case 0:
                    dimsension = 9;
                    break;
                case 1:
                    dimsension = 19;
                    break;
                default:
                    dimsension = 9;
                    break;
            }
            return dimsension;
        }
        private Game createGame()
        {
            BuilderGame.reset();    
            BuilderGame builder = BuilderGame.instance();
            String bolaBlanca = llenarBolaBlanca();
            String bolaNegra = llenarBolaNegra();
            builder.addPlayer(getJugador(Go.Tools.Color.White, bolaBlanca));
            builder.addPlayer(getJugador(Go.Tools.Color.Black, bolaNegra));
            builder.SizeBoard = llenarTablero();
            return builder.build();
        }

        private Tablero crearTablero()
        {
            Game game;
            game = createGame();
            if (es9x9())
                return Tablero.crearTablero9x9(game);
            else
                return Tablero.crearTablero19x19(game);
        }

        private Boolean es9x9()
        {
            return tamanoTablero.Text == TABLERO9x9;
        }

        private Player getJugador(Go.Tools.Color aColor, String value)
        {
            Player jugador;
            switch (value)
            {
                case JUGADORHUMANO:
                    jugador = new HumanPlayer(aColor, "Jugador"+ aColor);
                    break;
                case JUGADORCOMPUTADORA:
                    jugador = new ComputerPlayer(aColor, "Jugador" + aColor);
                    break;
                case JUGADORREMOTO:
                    if (this.socketCliente==null)
                    {
                        this.socketServer = waitForClient();
                        jugador = new LanPlayer(aColor, "Jugador" + aColor, this.socketServer);
                        colorJugadorRemoto = aColor;
                    }
                    else { jugador = new LanPlayer(aColor, "Jugador" + aColor, this.socketCliente); }
                    break;
                default:
                    jugador = new HumanPlayer(aColor, "JugadorBlanco");
                    break;
            }
            return jugador;
        }

        public Socket conectarSocket()
        {
            IPAddress direccion = IPAddress.Parse(IP);
            IPEndPoint Ep = new IPEndPoint(direccion, PORT);
            this.socketCliente = new Socket(Ep.AddressFamily, SocketType.Stream, ProtocolType.IP);
            try
            {
                this.socketCliente.Connect(Ep);
            }
            catch (Exception error)
            {
                this.socketCliente.Close();
            }
            return this.socketCliente;
        }

        private Socket waitForClient()
        {
            IPAddress direccion = IPAddress.Parse(IP);
            IPEndPoint ep = new IPEndPoint(direccion, PORT);
            Socket cliente = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.IP);
            try
            {
                cliente.Bind(ep); //lo bindeamos para que se ancle al puerto especificaco
            }
            catch (SocketException)
            {
                return null;
            }
            cliente.Listen(1);
            this.socketServer = cliente.Accept(); //Esto se queda esperando hasta que ocurra
            return this.socketServer;
        }

        public void reciveMesaje(Socket socketCliente)
        {
            string dataFromClient = null;
            byte[] bytesLeidos = new byte[TAMANIOTRANSFERENCIA];
            while (dataFromClient == null)
            {
                socketCliente.Receive(bytesLeidos, SocketFlags.None);
                dataFromClient = System.Text.Encoding.ASCII.GetString(bytesLeidos);
                dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("\n"));
            }

            if (dataFromClient != null)
            {
                String comando = dataFromClient.Substring(0, dataFromClient.IndexOf(" "));
                if (comando == TABLERO)
                {    
                    //leer desde el espacio hasta el final
                     dataFromClient=dataFromClient.Substring(10,(dataFromClient.Length-10));
                     tamanoTablero.SelectedText = dataFromClient;
                     textBox1.Text = dataFromClient;
                }

                else if (comando == "color")
                {
                    dataFromClient = dataFromClient.Substring(6, (dataFromClient.Length - 6));
                    textBox2.SelectedText = dataFromClient;
                    if (textBox2.Text == COLORNEGRO )
                        tipoJugadorNegra.SelectedIndex = 2;
                    else tipoJugadorBlanca.SelectedIndex = 2;
                }
            }
        }

        public void sendMessage(Socket socketServer, String mensaje)
        {
            Byte[] SendBytes = Encoding.ASCII.GetBytes(mensaje);
            try
            {
                socketServer.Send(SendBytes, SendBytes.Length, SocketFlags.None);
            }
            catch (Exception error) { }

        }

        private void playButton_Click_1(object sender, EventArgs e)
        {
            Tablero juego = crearTablero();
            if ((tipoJugadorBlanca.Text == JUGADORREMOTO) || (tipoJugadorNegra.Text == JUGADORREMOTO))
            {
                String mensaje_tablero = "boardsize " + tamanoTablero.Text + "\n";
                sendMessage(this.socketServer, mensaje_tablero);
                String mensaje_color = "color " + colorJugadorRemoto + "\n";
                sendMessage(this.socketServer, mensaje_color);
            }
            juego.Hide();
            juego.ShowDialog();
            juego.Dispose();
            this.Close();
        }


        private void button1_Click(object sender, EventArgs e)
        {
            this.panel1.Visible = false;
            this.panel2.Visible = true;
            this.socketCliente = conectarSocket();
            reciveMesaje(this.socketCliente);
            reciveMesaje(this.socketCliente);

        }

        private void button2_Click(object sender, EventArgs e)
        {
            Tablero juego = crearTablero();
            this.Hide();
            juego.ShowDialog();
            juego.Dispose();
            this.Close();
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) 
        {
            if (textBox2.Text == COLORNEGRO)
            {
                tipoJugadorBlanca.SelectedIndex = 2;
                if (comboBox1.SelectedIndex == 0)
                    tipoJugadorNegra.SelectedIndex = 0;
                else tipoJugadorNegra.SelectedIndex = 1;
            }
        }

        private void textBox1_TextChanged(object sender, EventArgs e)      {}
        private void tipoJugadorBlanca_SelectedIndexChanged(object sender, EventArgs e)       {}
        private void tipoJugadorNegra_SelectedIndexChanged(object sender, EventArgs e)      {}
        private void panel1_Paint(object sender, PaintEventArgs e)        {}
        private void label6_Click(object sender, EventArgs e)      { }
        private void panel2_Paint(object sender, PaintEventArgs e)       { }
        private void textBox2_TextChanged(object sender, EventArgs e){}
        private void label3_Click(object sender, EventArgs e) { }
       }
}
